#include <iostream>
#include <vector>
#include <pthread.h>
#include <time.h>
#include <unistd.h>
#include <semaphore.h>
using namespace std;

namespace my_ring_queue
{
    int s_cap = 5;
    template <class T>
    class RingQueue
    {
    private:
        vector<T> _ring_queue; //环形队列
        int _cap; //容量

        //信号量(资源计数器)，保证满或空状态下消费者生产者的线程安全
        sem_t _blank_sem; //生产者关心空位置资源
        sem_t _data_sem; //消费者关心数据资源

        //互斥锁，保证消费者和消费者，生产者和生产者之间的线程安全
        pthread_mutex_t _p_mtx; //生产者锁
        pthread_mutex_t _c_mtx; //消费者锁

        //位置
        int _p_step;
        int _c_step;

    public:
        RingQueue(int cap = s_cap):_cap(cap), _ring_queue(cap), _p_step(0), _c_step(0)
        {
            sem_init(&_blank_sem, 0 , cap);
            sem_init(&_data_sem, 0 , 0);
            pthread_mutex_init(&_p_mtx, nullptr);
            pthread_mutex_init(&_c_mtx, nullptr);
        }
        ~RingQueue()
        {
            sem_destroy(&_blank_sem);
            sem_destroy(&_data_sem);
            pthread_mutex_destroy(&_p_mtx);
            pthread_mutex_destroy(&_c_mtx);
        }

        //生产者
        void Push(const T& data)
        {
            //先申请自己资源(_blank_sem)
            sem_wait(&_blank_sem);
            //上锁
            pthread_mutex_lock(&_p_mtx);
            _ring_queue[_p_step] = data;

            _p_step++;
            _p_step %= _cap;
            //解锁
            pthread_mutex_unlock(&_p_mtx);
            //再释放对方资源(_data_sem)
            sem_post(&_data_sem);
        }
        //消费者
        void Pop(T* data)
        {
            //先申请自己资源(_data_sem)
            sem_wait(&_data_sem);
            //上锁
            pthread_mutex_lock(&_c_mtx);
            *data = _ring_queue[_c_step];

            _c_step++;
            _c_step %= _cap;
            //解锁
            pthread_mutex_unlock(&_c_mtx);
            //再释放对方资源(_blank_sem)
            sem_post(&_blank_sem); 
        }
    };
}


